package crmdna.keyvaluestore;

import static crmdna.common.AssertUtils.ensure;
import static crmdna.common.AssertUtils.ensureNotNull;
import static crmdna.common.OfyService.ofy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class KeyValueStoreCore {
  static void put(String namespace, String keyType, Map<String, Object> keysAndValues) {

    ensureNotNull(namespace, "namespace is null");

    ensureNotNull(keyType, "keyType is null");
    ensure(keyType.length() > 0, "keyType is empty string");

    ensureNotNull(keysAndValues, "keysAndValues is null");

    List<KeyValueEntity> entities = new ArrayList<>(keysAndValues.size());

    for (String key : keysAndValues.keySet()) {
      ensureNotNull(key, "key is null");
      ensure(key.length() > 0, "key is empty string");

      Object value = keysAndValues.get(key);
      ensureNotNull(value, "value for key[" + key + "] is null");

      KeyValueEntity entity = new KeyValueEntity();
      entity.key = keyType + "||" + key;
      entity.value = value;
      entity.valueClassName = value.getClass().getName();
      entities.add(entity);
    }

    ofy(namespace).save().entities(entities);
  }

  static Map<String, Object> get(String namespace, String keyType, List<String> keys) {
    ensureNotNull(namespace, "namespace is null");

    ensureNotNull(keyType, "keyType is null");
    ensure(keyType.length() > 0, "keyType is empty string");

    ensureNotNull(keys, "keys is null");

    List<String> actualKeys = new ArrayList<>(keys.size());
    for (int i = 0; i < keys.size(); i++) {

      String key = keys.get(i);
      ensureNotNull(key, "key is null");

      String actualKey = keyType + "||" + key;
      actualKeys.add(actualKey);
    }

    Map<String, KeyValueEntity> map =
        ofy(namespace).load().type(KeyValueEntity.class).ids(actualKeys);

    Map<String, Object> m = new HashMap<>();
    for (String key : map.keySet()) {
      m.put(key, map.get(key).value);
    }

    return m;
  }
}
